import React, { Component, PureComponent } from 'react'
// PureComponent 父类，它可以对props基础数据类型进行优化更新处理
// 复杂的props属性数据进行优化就需要使用ShouldComponentUpdate生命周期方法来完成
//  它是需要你自己去进行验证判断
//   true 则继续 render
//   false 则停止 render
// 第三方工具库完成对对象的深比较
// npm i -S lodash
// isEqual 如果两个对象中的值相同则返回true,反之为false
import isEqual from 'lodash/isEqual'

// class Child extends PureComponent {
class Child extends Component {
  // 更新时
  state = {
    count: 100
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    console.log('Child -- getDerivedStateFromProps')
    return null
  }

  // 优化子组件渲染
  // 必须要有返回值 true/false
  // 形参
  //  + nextProps  最新的props数据
  //  + this.props 旧的props数据
  //  + nextState  最新的state数据
  //  + this.state 旧的state数据
  shouldComponentUpdate(nextProps, nextState) {
    // console.log(nextProps, this.props)
    // if (nextProps.name.value == this.props.name.value) {
    //   return false
    // }
    // return true

    // console.log(isEqual(nextProps, this.props))

    console.log('Child -- shouldComponentUpdate')

    return !isEqual(nextProps, this.props) || !isEqual(nextState, this.state)
  }

  // 在最近一次渲染输出（提交到 DOM 节点）之前调用  更新之前
  //  + 如果你定义了此方法，则一定要有 componentDidUpdate
  // 此方法可以有返回值，返回值可以传递到 componentDidUpdate中的参数3来接受
  // 形参
  //  + prevProps  更新之前的props数据
  //  + this.props 更新之后的props数据
  //  + prevState  更新之前的state数据
  //  + this.state 更新之后的state数据
  // 可以把此方法理解为 componentDidUpdate 前置方法，可以在此方法中完成一部份的工作，来分担 componentDidUpdate 中代码
  // 它执行的顺序要比父组件要早
  getSnapshotBeforeUpdate(prevProps, prevState) {
    // 屏幕宽度
    const screenWidth = window.outerWidth

    console.log('Child -- getSnapshotBeforeUpdate')

    return screenWidth
  }

  // 数据更新之后  --- 用到它可能多一些
  // 一定要不在此方法中去更新数据，否则会死循环
  // 形参
  //  + prevProps  更新之前的props数据
  //  + this.props 更新之后的props数据
  //  + prevState  更新之前的state数据
  //  + this.state 更新之后的state数据
  //  + snapshot 可选，如果有getSnapshotBeforeUpdate钩子函数且它有返回值，才需要它
  componentDidUpdate(prevProps, prevState, snapshot) {
    // console.log('屏幕宽度为：', snapshot)
    console.log('Child -- componentDidUpdate')
  }

  render() {
    console.log('Child -- render')
    return (
      <div>
        <h3>count:{this.state.count}</h3>
        <button
          onClick={() => {
            this.setState((state) => ({
              count: state.count + 1
            }))
          }}
        >
          ++count++
        </button>
      </div>
    )
  }
}

class App extends Component {
  state = {
    // name: '张三'
    name: { value: '张三' }
  }
  static getDerivedStateFromProps(nextProps, prevState) {
    console.log('App -- getDerivedStateFromProps')
    return null
  }

  shouldComponentUpdate(nextProps, nextState) {
    console.log('App -- shouldComponentUpdate')
    return true
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log('App -- getSnapshotBeforeUpdate')
    return 1
  }

  // 数据更新之后
  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log('App -- componentDidUpdate')
  }

  render() {
    console.log('App -- render')
    return (
      <div>
        App:
        {/* <input
          type="text"
          value={this.state.name}
          onChange={(e) => this.setState({ name: e.target.value })}
        /> */}
        <button
          onClick={() => {
            this.setState({
              name: { value: Date.now() }
              // name: { value: '张三' }
            })
          }}
        >
          修改name
        </button>
        <hr />
        <Child name={this.state.name} />
      </div>
    )
  }
}

export default App
